package cloudeval.spec

import cn.edu.neu.vmmigeval.cloud.entity.*
import cn.edu.neu.vmmigeval.cloud.policy.VMDeployment

import java.util.concurrent.atomic.AtomicInteger

/**
 * The virtual machine specification.
 *
 * @author yfwz100
 */
class DataCenterBrokerSpec {

    private final static AtomicInteger counter = new AtomicInteger()

    class VMSpec {

        private int freq, ram, disk, bw
        private VMDeployment deployment

        void cpuFreq(int freq) {
            this.freq = freq
        }

        void ram(int ram) {
            this.ram = ram
        }

        void disk(int disk) {
            this.disk = disk
        }

        void bandwidth(int bw) {
            this.bw = bw
        }

        void deployment(VMDeployment deployment) {
            this.deployment = deployment
        }

        Vm createVM() {
            // todo cloudlet scheduler.
            new Vm(counter.incrementAndGet(), freq, ram, bw, disk, null)
        }
    }

    private Map<VMSpec, Integer> vmSpecMap = new HashMap<>()

    VMSpec VM(int size, @DelegatesTo(VMSpec) Closure closure) {
        def spec = new VMSpec()
        def code = closure.rehydrate(spec, this, this)
        code.resolveStrategy = Closure.DELEGATE_ONLY
        code()
        vmSpecMap[spec] = size
        return spec
    }

    // todo how to define the scale in (Host,VM) mapping?
    DataCenterBroker createDataCenterBroker(DataCenter dataCenter) {
        counter.set(0)
        List<Vm> vms = new ArrayList<>()
        // link the host and VMs.
        vmSpecMap.each { vmSpec, size  ->
            for (int i = 0; i < size; i++) {
                Vm vm = vmSpec.createVM()
                VMDeployment deployment = vmSpec.deployment
                Host host = deployment.getHostForVm(vm, dataCenter)
                host.vmList.add vm
                vm.host = host
                vms.add vm
            }
        }
        DataCenterBroker broker = new DataCenterBroker()
        broker.vms = vms
        broker.cloudlets = new LinkedList<>()
        return broker
    }

}
